piXoneer Development Library
XDL 3.0 for C#
NXPlanetView를 활용하여 구 기반 2D 도시 환경에서 기능활용법을 익히고 마우스 위치에 따른 좌표 도시, 나침반 도시, 도시 기능을 구현해 봅니다.
본 예제 프로그램은 NXPlanetView와 NXPlantLayer를 이용하여 Planet2D 모드 상에서 기본 사용법을 익히고 간단한 도시기능을 추가합니다.
“다음” 버튼을 눌러 프로젝트의 이름(XDL_PlanetView1)을 입력하고 [새 프로젝트] 대화상자의 “만들기” 버튼을 클릭한다. “만들기” 버튼을 누르면 프로젝트가 기본적으로 생성되고, 화면에 Form을 디자인할 수 있는 화면이 생성된다. 만약 아래와 같이 Form 디자인 화면이 생성되지 않으면, [솔루션 탐색기] 창에서 “Form1.cs”를 마우스 더블 클릭하여 디자인화면을 연다.
[도구 상자] 창의 “일반”에서 마우스 오른쪽 버튼을 클릭하여 생성되는 팝업메뉴에서 “항목 선택” 메뉴를 선택한다.
메뉴를 선택하면 아래와 같이 [도구 상자 항목 선택] 대화상자가 나타나며, 대화상자 아래쪽에 있는 “찾아보기” 버튼을 클릭한다. 열기 대화상자에서 “C:\Pixoneer\XDL3.0\bin\NXPlanet.dll” 파일을 선택한 후 “열기”를 클릭하고, [도구 상자 항목 선택] 대화상자의 “확인” 버튼을 클릭한다.
.NET Framework 구성요소 탭에 다양한 레이어와 NXPlanetView가 설정된다. “확인”버튼을 클릭한다. [도구상자]에 다양한 PlanetLayer들과 NXPlanetView가 추가됨을 확인한다.
번호 | Name | Control type | Caption | Items |
---|---|---|---|---|
(1) | checkBoxInverseMouseButton | CheckBox | InverseMouseButton | |
(2) | checkBoxInverseMouseWheel | CheckBox | InverseMouseWheel | |
(3) | checkBoxRotatable | CheckBox | Rotatable | |
(4) | comboBoxGrid | ComboBox | None Degrees GARS |
|
(5) | comboBoxScale | ComboBox | 1000000 500000 100000 50000 10000 |
|
(6) | buttonScaleApply | Button | Apply | |
(7) | checkBoxShowPBP | CheckBox | Show PBP | |
(8) | checkBoxShowStar | CheckBox | Show Star | |
(9) | checkBoxStatusInfo | CheckBox | Show StatusInfo | |
(10) | nxPlanetView1 | NXPlanetView | ||
(11) | nxPlanetLayer1 | NXPlanetLayer |
Form1에 splitContainer1이 추가되며 아래와 같이 “Panel1”과 “Panel2”가 생긴다. Panel1에는 (1)~(9)의 컨트롤을 추가하여 디자인하고, Panel2에는 (10), (11) 컨트롤을 추가한다. Panel1의 디자인은 위의 표를 참고로 구성하도록 하며 여기에서는 생략하도록 한다.
Form1.Designer.cs에서 보면 컨트롤 nxPlanetView1 멤버변수가 추가됨을 확인할 수 있다. NXPlanetView는 다양한 NXPlanetLayer들을 담을 수 있는 컨테이너이다. 즉, NXPlanetView는 다양한 계층의 레이어로 구성하여 구 기반 기능을 다양하게 구현할 수 있다.
NXPlanetLayer는 PlanetView에 추가되어 XDL 엔진에서 발생하는 이벤트를 외부 어플리케이션에서 처리할 수 있다. Form1.Designer.cs에서 보면 다음과 같이 컨트롤 nxPlanetLayer1 멤버변수가 추가됨을 확인할 수 있다.
C#
private System.Windows.Forms.SplitContainer splitContainer1;
private Pixoneer.NXDL.NXPlanet.NXPlanetView nxPlanetView1;
private Pixoneer.NXDL.NXPlanet.NXPlanetLayer nxPlanetLayer1;
“Load” 이벤트를 더블 클릭하면, “Form1_Load” 함수가 자동적으로 추가되고 아래와 같이 추가적인 기능을 구현할 수 있도록 Form1.cs의 코드로 이동하는 것을 확인할 수 있다.
Form1_Load 함수와 함께 아래와 같이 코드를 추가한다.
C#
using Pixoneer.NXDL;
using Pixoneer.NXDL.NGR;
using Pixoneer.NXDL.NXPlanet;
namespace XDL_PlanetView1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
nxPlanetView1.BackColor = Color.Black;
}
private void Form1_Load(object sender, EventArgs e)
{
// Camera 위치 설정
XGeoPoint gpEye = XGeoPoint.FromDegree(127.4, 38.0, 1500000);
nxPlanetView1.SetCameraPosition(gpEye, XAngle.FromDegree(0.0));
// 컨트롤의 초기 설정
checkBoxInverseMouseButton.Checked = nxPlanetView1.InverseMouseButton;
checkBoxInverseMouseWheel.Checked = nxPlanetView1.InverseMouseWheel;
checkBoxRotatable.Checked = nxPlanetView1.Rotatable;
checkBoxShowPBP.Checked = nxPlanetView1.ShowPBP;
checkBoxShowStar.Checked = true;
checkBoxShowStatusInfo.Checked = nxPlanetView1.ShowStatusInfo;
if (nxPlanetView1.GridType == NXPlanetView.eGridType.GridNone)
comboBoxGrid.SelectedIndex = 0;
else if (nxPlanetView1.GridType == NXPlanetView.eGridType.GridDegrees)
comboBoxGrid.SelectedIndex = 1;
else if (nxPlanetView1.GridType == NXPlanetView.eGridType.GridGARS)
comboBoxGrid.SelectedIndex = 2;
else
comboBoxGrid.SelectedIndex = 0;
// 화면 갱신 요청
nxPlanetView1.RefreshScreen();
}
}
}
컨트롤에서 마우스로 더블 클릭하면 대표적인 이벤트에 대해 자동적으로 함수가 추가된다.
아래와 같이 코드를 추가한다.
C#
private void checkBoxInverseMouseButton_CheckedChanged(object sender, EventArgs e)
{
// PlanetView는 기본적으로 마우스 왼쪽 버튼은 화면이동을, 오른쪽 버튼은 화면회전 기능을 담당한다.
// 이 기능을 전환하려면 NXPlanetView의 InserverMouseButton을 true로 설정하면 된다.
nxPlanetView1.InverseMouseButton = checkBoxInverseMouseButton.Checked;
}
private void checkBoxInverseMouseWheel_CheckedChanged(object sender, EventArgs e)
{
// PlanetView는 기본적으로 마우스 휠을 당기면 화면확대가, 밀면 화면축소가 된다.
// 이을 전환하려면 NXPlanetView의 InverseMouseWheel을 true로 설정하면 된다.
nxPlanetView1.InverseMouseWheel = checkBoxInverseMouseWheel.Checked;
}
private void checkBoxRotatable_CheckedChanged(object sender, EventArgs e)
{
// NXPlanetView의 Rotatble 속성을 설정하면 화면회전 여부를 설정할 수 있다.
nxPlanetView1.Rotatable = checkBoxRotatable.Checked;
}
private void comboBoxGrid_SelectedIndexChanged(object sender, EventArgs e)
{
int gridIndex = comboBoxGrid.SelectedIndex;
if (gridIndex == 0) // none
nxPlanetView1.GridType = NXPlanetView.eGridType.GridNone;
else if (gridIndex == 1) // Degrees
nxPlanetView1.GridType = NXPlanetView.eGridType.GridDegrees;
else if (gridIndex == 2) // GARS
nxPlanetView1.GridType = NXPlanetView.eGridType.GridGARS;
}
private void buttonScaleApply_Click(object sender, EventArgs e)
{
double mapAltitude = 1500000.0;
int scaleIndex = comboBoxScale.SelectedIndex;
if (scaleIndex == 0) // 1000000
mapAltitude = nxPlanetView1.GetMapAltitude(NXPlanetView.eMapScale.Scale_1000000);
else if (scaleIndex == 1) // 500000
mapAltitude = nxPlanetView1.GetMapAltitude(NXPlanetView.eMapScale.Scale_500000);
else if (scaleIndex == 2) // 100000
mapAltitude = nxPlanetView1.GetMapAltitude(NXPlanetView.eMapScale.Scale_100000);
else if (scaleIndex == 3) // 50000
mapAltitude = nxPlanetView1.GetMapAltitude(NXPlanetView.eMapScale.Scale_50000);
else if (scaleIndex == 4) // 10000
mapAltitude = nxPlanetView1.GetMapAltitude(NXPlanetView.eMapScale.Scale_10000);
// 현재의 camera 정보 가져오기
NXCameraState state = nxPlanetView1.GetCameraState();
XGeoPoint eyePos = new XGeoPoint();
eyePos.lond = state.lonEye.deg;
eyePos.latd = state.latEye.deg;
eyePos.hgt = mapAltitude;
// 위치를 유지한 상태로 카메라의 높이만 수정하여 설정
nxPlanetView1.SetCameraPosition(eyePos, XAngle.FromDegree(0.0));
nxPlanetView1.RefreshScreen();
}
private void checkBoxShowPBP_CheckedChanged(object sender, EventArgs e)
{
// 지형 지도 위에 텍스트형태의 지명을 중첩하여 도시할 수 있는데, 이에 대한 여부를 설정한다.
nxPlanetView1.ShowPBP = checkBoxShowPBP.Checked;
nxPlanetView1.RefreshScreen();
}
private void checkBoxShowStar_CheckedChanged(object sender, EventArgs e)
{
// 화면 축소를 해서 지도 영역 밖으로 벗어나는 경우, 배경 별을 추가도시 여부를 설정한다.
nxPlanetView1.ShowStar = checkBoxShowStar.Checked;
nxPlanetView1.RefreshScreen();
}
private void checkBoxShowStatusInfo_CheckedChanged(object sender, EventArgs e)
{
// XDL 엔진의 도시 상태 정보를 화면에 도시 여부를 설정한다.
nxPlanetView1.ShowStatusInfo = checkBoxShowStatusInfo.Checked;
nxPlanetView1.RefreshScreen();
}
마지막으로 View상에서 마우스 위치에 대한 좌표를 화면도시하고, 나침반을 화면에 추가하도록 하겠다. 먼저 마우스 화면 좌표를 저장하는 변수와 화면도시를 위한 변수를 생성한다.
C#
public partial class Form1 : Form
{
private XVertex2d scrPos = new XVertex2d();
private XTextPrinter textPrinter = new XTextPrinter();
private XTexture compassTexture = new XTexture();
public Form1()
{
InitializeComponent();
nxPlanetView1.BackColor = Color.Black;
Font coordFont = new Font("Gulim", 12, FontStyle.Regular | FontStyle.Bold);
if (!textPrinter.Initialize(coordFont))
{
System.Diagnostics.Debug.WriteLine("Fail to initialize text printer for coordinate display!");
}
if (!compassTexture.Load("c:\\Pixoneer\\XDL3.0\\Resource\\compass.png "))
{
System.Diagnostics.Debug.WriteLine("Fail to load compass texture!");
}
}
...
}
나침반 이미지로 사용하는 “compass.png” 파일이 예제 코드와 같은 경로에 없으면, 예제 샘플 프로그램 압축 파일에 있는 파일을 이용하기 바란다.
OnWndProc 이벤트는 NXPlanetLayer가 추가되어 있는 View의 윈도우 이벤트를 외부에서 받아서 사용할 수 있도록 한다. OnOrthoRender는 NXPlanetLayer가 추가되어 있는 View의 Ortho-rendering이 완료된 후 어플리케이션에서 추가적인 작업을 구현해야 할 필요가 있을 때 사용하면 된다. 참고로 NXPlanetView의 내부 Rendering 수행->OnRender 이벤트 발생->NXPlanetView의 내부 OrthoRendering 수행->OnOrthoRender 이벤트 발생 순서로 이루어진다. 코드는 아래와 같다.
C#
private bool nxPlanetLayer1_OnWndProc(object sender, NXPlanetDrawArgs e, ref Message m)
{
if (m.Msg == Pixoneer.NXDL.XWndMsg.XWM_MOUSEMOVE)
{
scrPos.x = Pixoneer.NXDL.XWndMsg.GetLowValue(m.LParam);
scrPos.y = Pixoneer.NXDL.XWndMsg.GetHighValue(m.LParam);
nxPlanetView1.RefreshScreen();
}
return default(bool);
}
private bool nxPlanetLayer1_OnOrthoRender(object sender, NXPlanetDrawArgs e)
{
if (nxPlanetView1 == null) return false;
XVertex3d posWorld = new XVertex3d();
// 화면 좌표를 위경도 좌표로 변환
XGeoPoint gpPoint = nxPlanetView1.ScreenToGeographic(scrPos.x, scrPos.y);
posWorld.x = scrPos.x;
posWorld.y = scrPos.y;
posWorld.z = 0.0;
String str = gpPoint.lond.ToString() + ", " + gpPoint.latd.ToString();
// 화면에 텍스트 좌표를 도시
bool result = textPrinter.Print(str, posWorld, Pixoneer.NXDL.NGR.eTextAlign.Align_Center, Color.White, true, Color.DarkBlue);
// 나침반 도시
if (!compassTexture.SendTextureToDevice()) return false;
NXCameraState state = nxPlanetView1.GetCameraState();
int nXSize = compassTexture.Width;
int nYSize = compassTexture.Height;
e.Graphics.glDisable(XGraphics.GL_DEPTH_TEST);
e.Graphics.glEnable(XGraphics.GL_BLEND);
e.Graphics.glBindTexture(XGraphics.GL_TEXTURE_2D, (uint)compassTexture.GLTextureID);
e.Graphics.glColor3f(1.0f, 1.0f, 1.0f);
e.Graphics.glPushMatrix();
e.Graphics.glTranslated(100.0, 100.0);
e.Graphics.glRotated(-state.azimuth.deg, 0.0, 0.0, 1.0);
e.Graphics.glBegin(XGraphics.GL_QUADS);
e.Graphics.glTexCoord2f(0, 1); e.Graphics.glVertex3d(-nXSize / 2, -nYSize / 2, 0);
e.Graphics.glTexCoord2f(0, 0); e.Graphics.glVertex3d(-nXSize / 2, nYSize / 2, 0);
e.Graphics.glTexCoord2f(1, 0); e.Graphics.glVertex3d(nXSize / 2, nYSize / 2, 0);
e.Graphics.glTexCoord2f(1, 1); e.Graphics.glVertex3d(nXSize / 2, -nYSize / 2, 0);
e.Graphics.glEnd();
e.Graphics.glPopMatrix();
e.Graphics.glDisable(XGraphics.GL_BLEND);
e.Graphics.glEnable(XGraphics.GL_DEPTH_TEST);
return default(bool);
}
“다음” 버튼을 눌러 사용자가 원하는 경로를 선택한 다음 프로젝트 이름을 “XDL_PlanetView1” 으로 입력하고 [새 프로젝트] 대화상자의 “만들기” 버튼을 클릭한다. “만들기” 버튼을 누르면 프로젝트가 기본적으로 생성되고, 화면에 Window을 디자인할 수 있는 화면이 뜬다. 만약 아래와 같은 Window 창이 생성되지 않으면, [솔루션 탐색기] 창에서 “MainWindow.xaml”를 마우스 더블클릭을 하여 창을 연다.
번호 | Name | Control type | Content | Items |
---|---|---|---|---|
(1) | checkBoxInverseMouseButton | CheckBox | InverseMouseButton | |
(2) | checkBoxInverseMouseWheel | CheckBox | InverseMouseWheel | |
(3) | checkBoxRotatable | CheckBox | Rotatable | |
(4) | comboBoxGrid | ComboBox | None Degrees GARS |
|
(5) | comboBoxScale | ComboBox | 1000000 500000 100000 50000 10000 |
|
(6) | buttonScaleApply | Button | Apply | |
(7) | checkBoxShowPBP | CheckBox | Show PBP | |
(8) | checkBoxShowStar | CheckBox | Show Star | |
(9) | checkBoxStatusInfo | CheckBox | Show StatusInfo | |
(10) | nxPlanetView1 | NXPlanetView | ||
(11) | nxPlanetLayer1 | NXPlanetLayer |
먼저 Grid를 세 개의 Column으로 나눈다. 그 다음으로 첫 번째 Column에 도구상자를 이용하여 CheckBox와 Button 컨트롤 등을 이용해 디자인한다(표 참고). 자세한 XAML코드는 샘플을 참고한다.
XAML
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="210"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
…
</Grid>
</Grid>
XAML
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="210"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
…
</Grid>
<GridSplitter Grid.Column="1"/>
</Grid>
XAML
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="210"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
…
</Grid>
<GridSplitter Grid.Column="1"/>
<WindowsFormsHost Grid.Column="2" Margin="3,0,0,3">
<nxPlanet:NXPlanetView x:Name="nxPlanetView1">
</nxPlanet:NXPlanetView>
</WindowsFormsHost>
</Grid>
XAML
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="210"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
…
</Grid>
<GridSplitter Grid.Column="1"/>
<WindowsFormsHost Grid.Column="2" Margin="3,0,0,3">
<nxPlanet:NXPlanetView x:Name="nxPlanetView1">
<nxPlanet:NXPlanetView.Controls>
<nxPlanet:NXPlanetLayer x:Name="nxPlanetLayer1"/>
</nxPlanet:NXPlanetView.Controls>
</nxPlanet:NXPlanetView>
</WindowsFormsHost>
</Grid>
NXPlanetView는 다양한 NXPlanetLayer들을 담을 수 있는 컨테이너이다 즉, NXPlanetView는 다양한 레이어를 구성하여 구 기반 기능을 다양하게 구현할 수 있다. NXPlanetLayer는 PlanetView에 추가되어 XDL 엔진에서 발생하는 이벤트를 외부 어플리케이션에서 처리할 수 있다. 디자인이 완료되면 아래와 같은 창을 얻을 수 있다.
“Loaded” 이벤트를 더블 클릭하면, “Window_Loaded” 함수가 자동적으로 추가되고 아래와 같이 추가적인 기능을 구현할 수 있도록 MainWindow.xaml.cs으로 이동하는 것을 확인할 수 있다. 아래와 같이 코드를 추가한다.
C#
using Pixoneer.NXDL;
using Pixoneer.NXDL.NGR;
using Pixoneer.NXDL.NXPlanet;
namespace XDL_PlanetView1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
nxPlanetView1.BackColor = System.Drawing.Color.Black;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Camera 위치 설정
XGeoPoint gpEye = XGeoPoint.FromDegree(127.4, 38.0, 1500000);
nxPlanetView1.SetCameraPosition(gpEye, XAngle.FromDegree(0.0));
// 컨트롤의 초기 설정
checkBoxInverseMouseButton.IsChecked = nxPlanetView1.InverseMouseButton;
checkBoxInverseMouseWheel.IsChecked = nxPlanetView1.InverseMouseWheel;
checkBoxRotatable.IsChecked = nxPlanetView1.Rotatable;
checkBoxShowPBP.IsChecked = nxPlanetView1.ShowPBP;
checkBoxShowStar.IsChecked = true;
checkBoxStatusInfo.IsChecked = nxPlanetView1.ShowStatusInfo;
if (nxPlanetView1.GridType == NXPlanetView.eGridType.GridNone)
comboBoxGrid.SelectedIndex = 0;
else if (nxPlanetView1.GridType == NXPlanetView.eGridType.GridDegrees)
comboBoxGrid.SelectedIndex = 1;
else if (nxPlanetView1.GridType == NXPlanetView.eGridType.GridGARS)
comboBoxGrid.SelectedIndex = 2;
else
comboBoxGrid.SelectedIndex = 0;
// 화면 갱신 요청
nxPlanetView1.RefreshScreen();
}
}
}
컨트롤에서 마우스로 더블 클릭하면 대표적인 이벤트에 대해 자동적으로 함수가 추가된다. 아래와 같이 코드를 MainWindow.xaml.cs에 추가한다.
C#
private void checkBoxInverseMouseButton_Checked(object sender, RoutedEventArgs e)
{
// PlanetView는 기본적으로 마우스 왼쪽 버튼은 화면 이동을, 오른쪽 버튼은 화면회전 기능을 담당한다.
// 이 기능을 전환하려면 NXPlanetView의 InverseMouseButton을 true로 설정하면 된다.
nxPlanetView1.InverseMouseButton = true;
}
private void checkBoxInverseMouseButton_UnChecked(object sender, RoutedEventArgs e)
{
// PlanetView는 기본적으로 마우스 왼쪽 버튼은 화면 이동을, 오른쪽 버튼은 화면회전 기능을 담당한다.
// 이 기능을 전환 후 해제하려면 NXPlanetView의 InverseMouseButton을 false로 설정하면 된다.
nxPlanetView1.InverseMouseButton = false;
}
private void checkBoxInverseMouseWheel_Checked(object sender, RoutedEventArgs e)
{
// PlanetView는 기본적으로 마우스 왼쪽 버튼은 화면 이동을, 오른쪽 버튼은 화면회전 기능을 담당한다.
// 이 기능을 전환하려면 NXPlanetView의 InverseMouseButton을 true로 설정하면 된다.
nxPlanetView1.InverseMouseWheel = true;
}
private void checkBoxInverseMouseWheel_Unchecked(object sender, RoutedEventArgs e)
{
// PlanetView는 기본적으로 마우스 왼쪽 버튼은 화면 이동을, 오른쪽 버튼은 화면회전 기능을 담당한다.
// 이 기능을 전환 후 해제하려면 NXPlanetView의 InverseMouseButton을 false로 설정하면 된다.
nxPlanetView1.InverseMouseWheel = false;
}
private void checkBoxRotatable_Checked(object sender, RoutedEventArgs e)
{
// NXPlanetView의 Rotatable 속성을 설정하려면 화면회전 여부를 설정할 수 있다.
nxPlanetView1.Rotatable = true;
}
private void checkBoxRotatable_Unchecked(object sender, RoutedEventArgs e)
{
// NXPlanetView의 Rotatable 속성을 설정하려면 화면회전 여부를 설정할 수 있다.
nxPlanetView1.Rotatable = false;
}
private void comboBoxGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (comboBoxGrid.SelectedIndex == 0) // None
{
nxPlanetView1.GridType = NXPlanetView.eGridType.GridNone;
}
else if (comboBoxGrid.SelectedIndex == 1) // Degree
{
nxPlanetView1.GridType = NXPlanetView.eGridType.GridDegrees;
}
else if (comboBoxGrid.SelectedIndex == 2) // GARS
{
nxPlanetView1.GridType = NXPlanetView.eGridType.GridGARS;
}
}
이어서 코드를 추가한다.
C#
private void buttonScaleApply_Click(object sender, RoutedEventArgs e)
{
double mapAltitude = 1500000.0;
int scaleIndex = comboBoxScale.SelectedIndex;
if (scaleIndex == 0) // 1000000
mapAltitude = nxPlanetView1.GetMapAltitude(NXPlanetView.eMapScale.Scale_1000000);
else if (scaleIndex == 1) // 500000
mapAltitude = nxPlanetView1.GetMapAltitude(NXPlanetView.eMapScale.Scale_500000);
else if (scaleIndex == 2) // 100000
mapAltitude = nxPlanetView1.GetMapAltitude(NXPlanetView.eMapScale.Scale_100000);
else if (scaleIndex == 3) // 50000
mapAltitude = nxPlanetView1.GetMapAltitude(NXPlanetView.eMapScale.Scale_50000);
else if (scaleIndex == 4) // 10000
mapAltitude = nxPlanetView1.GetMapAltitude(NXPlanetView.eMapScale.Scale_10000);
// 현재의 Camera 정보 가져오기
NXCameraState state = nxPlanetView1.GetCameraState();
XGeoPoint eyePos = new XGeoPoint();
eyePos.lond = state.lonEye.deg;
eyePos.latd = state.latEye.deg;
eyePos.hgt = mapAltitude;
// 위치를 유지한 상태로 카메라의 높이만 수정하여 설정
nxPlanetView1.SetCameraPosition(eyePos, XAngle.FromDegree(0.0));
nxPlanetView1.RefreshScreen();
}
private void checkBoxShowPBP_Checked(object sender, RoutedEventArgs e)
{
// 지형 지도 위에 텍스트형태의 지명을 중첩하여 도시할 수 있는데, 이에 대한 여부를 설정한다.
nxPlanetView1.ShowPBP = true;
nxPlanetView1.RefreshScreen();
}
private void checkBoxShowPBP_Unchecked(object sender, RoutedEventArgs e)
{
// 지형 지도 위에 텍스트형태의 지명을 중첩하여 도시할 수 있는데, 이에 대한 여부를 설정한다.
nxPlanetView1.ShowPBP = false;
nxPlanetView1.RefreshScreen();
}
private void checkBoxShowStar_Checked(object sender, RoutedEventArgs e)
{
// 화면 축소를 해서 지도 영역 밖으로 벗어나는 경우, 배경 별을 추가도시 여부를 설정한다.
nxPlanetView1.ShowStar = true;
nxPlanetView1.RefreshScreen();
}
private void checkBoxShowStar_Unchecked(object sender, RoutedEventArgs e)
{
// 화면 축소를 해서 지도 영역 밖으로 벗어나는 경우, 배경 별을 추가도시 여부를 설정한다.
nxPlanetView1.ShowStar = false;
nxPlanetView1.RefreshScreen();
}
private void checkBoxStatusInfo_Checked(object sender, RoutedEventArgs e)
{
// XDL 엔진의 도시 상태 정보를 화면에 도시 여부를 설정한다.
nxPlanetView1.ShowStatusInfo = true;
nxPlanetView1.RefreshScreen();
}
private void checkBoxStatusInfo_Unchecked(object sender, RoutedEventArgs e)
{
// XDL 엔진의 도시 상태 정보를 화면에 도시 여부를 설정한다.
nxPlanetView1.ShowStatusInfo = false;
nxPlanetView1.RefreshScreen();
}
마지막으로 View상에서 마우스 위치에 대한 좌표를 화면도시하고, 나침반을 화면에 추가하도록 하겠다. 먼저 마우스 화면 좌표를 저장하는 변수와 화면도시를 위한 변수를 생성한다.
C#
public partial class MainWindow : Window
{
// 마우스 화면 좌표를 저장하는 변수와 화면도시를 위한 변수생성
private XVertex2d scrPos = new XVertex2d();
private XTextPrinter textPrinter = new XTextPrinter();
private XTexture compassTexture = new XTexture();
public MainWindow()
{
InitializeComponent();
nxPlanetView1.BackColor = System.Drawing.Color.Black;
Font coordFont = new Font("Gulim", 12, System.Drawing.FontStyle.Regular | System.Drawing.FontStyle.Bold);
if (!textPrinter.Initialize(coordFont))
{
System.Diagnostics.Debug.WriteLine("Fail to initialize text printer for coordinate display!");
}
if (!compassTexture.Load("c:\\Pixoneer\\XDL3.0\\Resource\\compass.png"))
{
System.Diagnostics.Debug.WriteLine("Fail to load compass texture!");
}
}
}
나침반 이미지로 사용하는 “compass.png” 파일이 예제 코드와 같은 경로에 없으면, 예제 샘플 프로그램 압축 파일에 있는 파일을 이용하기 바란다.
OnWndProc 이벤트는 NXPlanetLayer가 추가되어 있는 View의 윈도우 이벤트를 외부에서 받아서 사용할 수 있도록 한다. OnOrthoRender는 NXPlanetLayer가 추가되어 있는 View의 Ortho-rendering이 완료된 후 어플리케이션에서 추가적인 작업을 구현해야 할 필요가 있을 때 사용하면 된다. 참고로 NXPlanetView의 내부 Rendering 수행->OnRender 이벤트 발생->NXPlanetView의 내부 OrthoRendering 수행->OnOrthoRender 이벤트 발생 순서로 이루어진다. 코드는 아래와 같다.
C#
private bool nxPlanetLayer1_OnWndProc(object sender, NXPlanetDrawArgs e, ref System.Windows.Forms.Message m)
{
if (m.Msg == Pixoneer.NXDL.XWndMsg.XWM_MOUSEMOVE)
{
scrPos.x = Pixoneer.NXDL.XWndMsg.GetLowValue(m.LParam);
scrPos.y = Pixoneer.NXDL.XWndMsg.GetHighValue(m.LParam);
nxPlanetView1.RefreshScreen();
}
return default(bool);
}
private bool nxPlanetLayer1_OnOrthoRender(object sender, NXPlanetDrawArgs e)
{
if (nxPlanetView1 == null) return false;
XVertex3d posWorld = new XVertex3d();
// 화면 좌표를 위경도 좌표로 변환
XGeoPoint gpPoint = nxPlanetView1.ScreenToGeographic(scrPos.x, scrPos.y);
posWorld.x = scrPos.x;
posWorld.y = scrPos.y;
posWorld.z = 0.0;
String str = gpPoint.lond.ToString() + ", " + gpPoint.latd.ToString();
// 화면에 텍스트 좌표를 도시
bool result = textPrinter.Print(str, posWorld, Pixoneer.NXDL.NGR.eTextAlign.Align_Center, System.Drawing.Color.White, true, System.Drawing.Color.DarkBlue);
// 나침반 도시
if (!compassTexture.SendTextureToDevice()) return false;
NXCameraState state = nxPlanetView1.GetCameraState();
int nXSize = compassTexture.Width;
int nYSize = compassTexture.Height;
e.Graphics.glDisable(XGraphics.GL_DEPTH_TEST);
e.Graphics.glEnable(XGraphics.GL_BLEND);
e.Graphics.glBindTexture(XGraphics.GL_TEXTURE_2D, (uint)compassTexture.GLTextureID);
e.Graphics.glColor3f(1.0f, 1.0f, 1.0f);
e.Graphics.glPushMatrix();
e.Graphics.glTranslated(100.0, 100.0);
e.Graphics.glRotated(-state.azimuth.deg, 0.0, 0.0, 1.0);
e.Graphics.glBegin(XGraphics.GL_QUADS);
e.Graphics.glTexCoord2f(0, 1); e.Graphics.glVertex3d(-nXSize / 2, -nYSize / 2, 0);
e.Graphics.glTexCoord2f(0, 0); e.Graphics.glVertex3d(-nXSize / 2, nYSize / 2, 0);
e.Graphics.glTexCoord2f(1, 0); e.Graphics.glVertex3d(nXSize / 2, nYSize / 2, 0);
e.Graphics.glTexCoord2f(1, 1); e.Graphics.glVertex3d(nXSize / 2, -nYSize / 2, 0);
e.Graphics.glEnd();
e.Graphics.glPopMatrix();
e.Graphics.glDisable(XGraphics.GL_BLEND);
e.Graphics.glEnable(XGraphics.GL_DEPTH_TEST);
return default(bool);
}